#include <string>
#include <vector>
#include <unistd.h>
#include <ctime>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include "task.hpp"
enum
{
    PIPE_ERROR = 1
};
const int processnum = 5;
std::vector<task_t> tasks;
class channel
{
public:
    channel(int cmdfd, pid_t slaverid, const std::string processname)
        : _cmdfd(cmdfd), _slaverid(slaverid), _processname(processname)
    {
    }

public:
    int _cmdfd;               // 发送任务的文件描述符
    pid_t _slaverid;          // 子进程PID
    std::string _processname; // 子进程名字
};
// 子进程执行任务
void Slaver()
{
    while (true)
    {
        // std::cout << getpid() << " " << "read fd is: " << rfd << std::endl;
        // sleep(1);
        int cmdcode = 0;
        int n = read(0, &cmdcode, sizeof(int));
        if (n == sizeof(int))
        {
            // 执行cmdcode对应的任务列表
            std::cout << getpid() << ": cmdcode: " << cmdcode << std::endl;
            if (cmdcode >= 0 && cmdcode <= tasks.size())
            {
                tasks[cmdcode]();
            }
        }
        if (n == 0)
        {
            break;
        }
    }
}
// 初始化进程池
void InitProcessPool(std::vector<channel> *channels)
{
    std::vector<int> oldfds;
    for (int i = 0; i < processnum; i++)
    {
        // 创建管道
        int pipefd[2];
        int n = pipe(pipefd);
        if (n < 0)
        {
            perror("pipe");
            exit(PIPE_ERROR);
        }

        pid_t id = fork();
        if (id == 0)
        {
            for (auto e : oldfds)
            {
                close(e);
            }
            close(pipefd[1]);
            dup2(pipefd[0], 0);
            Slaver();
            std::cout << "process: " << getpid() << " quit" << std::endl;
            // Slaver(pipefd[0]);
            exit(0);
        }
        close(pipefd[0]);
        std::string name = "process-" + std::to_string(i);
        channels->push_back(channel(pipefd[1], id, name));
        oldfds.push_back(pipefd[1]);
    }
}
void Debug(const std::vector<channel> &channels)
{
    for (const auto &e : channels)
    {
        std::cout << e._cmdfd << " " << e._slaverid << " " << e._processname << std::endl;
    }
}

void Menu()
{
    std::cout << "##############################################" << std::endl;
    std::cout << "#####1.刷新日志        2.刷新出来野怪      #####" << std::endl;
    std::cout << "#####3.检测软件是否更新 4.更新用户血量和蓝量#####" << std::endl;
    std::cout << "#####0.退出                          #########" << std::endl;
    std::cout << "#############################################" << std::endl;
    std::cout << "#############################################" << std::endl;
}
//选择子进程
void CtrlSlaver(const std::vector<channel> channels)
{
    // int cnt = 5;
    while (true)
    {
        int select = 0;
        Menu();
        std::cout << "Please Enter@ ";
        std::cin >> select;
        if (select <= 0 || select >= 5)
            break;
        // int cmdcode = rand() % tasks.size();
        int cmdcode = select - 1;
        int processpos = rand() % channels.size();
        std::cout << "father " << "cmdcode: " << cmdcode << "slaverid: " << channels[processpos]._slaverid
                  << "process name: " << channels[processpos]._processname << std::endl;
        write(channels[processpos]._cmdfd, &cmdcode, sizeof(cmdcode));
        // sleep(1);
    }
}
void QuitProcess(const std::vector<channel> &channels)
{
    for (const auto e : channels)
    {
        close(e._cmdfd);
        waitpid(e._slaverid, nullptr, 0);
    }
    // for (const auto e : channels)
    // {
    //     waitpid(e._slaverid, nullptr, 0);
    // }
}
int main()
{
    // 加载任务
    LoadTask(&tasks);
    srand(time(nullptr) ^ getpid() ^ 1023);
    std::vector<channel> channels;
    InitProcessPool(&channels);
    Debug(channels);
    CtrlSlaver(channels);

    QuitProcess(channels);
    return 0;
}